<?php
/**
 * 进入牌桌处理
 *
 * 获取牌桌基本信息
 * 玩家加入牌桌
 * 玩家加入牌桌的位置
 * 玩家离开牌桌
 * 解散牌桌
 */

namespace app\handle;

use app\common\utils\RedisUtils;
use app\common\model\TableModel;
use app\common\model\UserModel;
use app\common\model\UserGradeModel;
use app\handle\Game as hGame;

Class Table
{
    /**
     * 牌桌所有key
     *
     * @var array
     */
    public $key = array();

    /**
     * 牌桌id
     *
     * @var [type]
     */
    private $tid;

    /**
     * 用户id
     *
     * @var [type]
     */
    private $uid;

    /**
     * 牌桌配置
     *
     * @var [type]
     */
    public $config;

    /**
     * 返回结果
     *
     * @var [type]
     */
    public $result;

    public function __construct($tid, $uid)
    {
        $this->uid = $uid;
        $this->tid = $tid;
        $this->result = [
            'code' => 0,
            'msg'  => 'Error'
        ];

        $this->key = [
            /**
             * 玩家加入牌桌
             * key = uid
             * val = tid
             */
            'table'     => 'table_key_'.$uid,

            /**
             * 玩家加入牌桌位置
             * key = tid
             * val = [ uid, uid, ... ]
             */
            'pos'       => 'pos_key_'.$tid,

            /**
             * 牌桌的配置信息
             * key = tid
             * val = array
             */
            'config'    => 'config_key_'.$tid,

            /**
             * 牌桌的游戏状态
             * key = tid
             * val = false|true
             */
            'status'    => 'table_status_key_'.$tid,

            /**
             * 牌桌当前的局数
             * key = tid
             * val = number
             */
            'innings'   => 'innings_key_'.$tid,

            /**
             * 牌桌上用户信息
             * key = tid
             * val = array
             */
            'userinfo'  => 'userinfo_key_'.$tid,

            /**
             * 牌桌上连接id
             * key = tid
             * val = array
             */
            'conn'      => 'conn_key_'.$tid,
        ];

        // 牌桌配置信息
        $this->tableConfig();
    }

    /**
     * 存储连接id
     * @return [type] [description]
     */
    public function storageConnId($connid)
    {
        $conn = $this->getCids();
        if (empty($conn)) {
            $conn = [];
        }
        $conn = $this->rmRepeatArray($conn);

        // 判断是否已经存在
        foreach ($conn as $k => $v) {
            if ($v['uid'] == $this->uid) {
                unset($conn[$k]);
            }
        }

        $array = [
            'uid' => (int)$this->uid,
            'cid' => $connid
        ];
        array_push($conn, $array);

        if (count($conn) > 5) {
            return false;
        }
        $this->setCids($conn);
        return true;
    }

    /**
     * 去重
     * @param  [type] $conn [description]
     * @return [type]       [description]
     */
    public function rmRepeatArray($conn)
    {
        foreach ($conn as $k1 => $v1) {
            $count = 0;
            foreach ($conn as $k2 => $v2) {
                if ($v1['uid'] == $v2['uid']) {
                    $count++;
                    if ($count > 1) {
                        unset($conn[$k2]);
                        return $this->rmRepeatArray($conn);
                    }
                }
            }
        }
        return $conn;
    }

    /**
     * 获取牌桌cid
     * @return [type] [description]
     */
    public function getCids()
    {
        return RedisUtils::get($this->key['conn']);
    }

    /**
     * 设置牌桌cids
     * @param [type] $cids [description]
     */
    public function setCids($cids)
    {
        return RedisUtils::set($this->key['conn'], $cids);
    }

    /**
     * 根据Cid获取用户uid
     * @return [type] [description]
     */
    public function getUidByCid($cid)
    {
        $conn = RedisUtils::get($this->key['conn']);
        $uid  = 0;
        if (empty($conn)) $conn = [];

        foreach ($conn as $k => $v) {
            if ($v['cid'] == $cid) {
                $uid = $v['uid'];
                break;
            }
        }
        if (empty($uid) || $uid === 0) {
            return false;
        } else {
            return $uid;
        }
    }

    /**
     * 根据uid获取cid
     * @param  [type] $uid [description]
     * @return [type]      [description]
     */
    public function getCidByUid($uid)
    {
        $conn = RedisUtils::get($this->key['conn']);
        $cid  = 0;
        if (empty($conn)) $conn = [];

        foreach ($conn as $k => $v) {
            if ($v['uid'] == $uid) {
                $cid = $v['cid'];
                break;
            }
        }
        if (empty($cid) || $cid === 0) {
            return false;
        } else {
            return $cid;
        }
    }

    /**
     * 断开连接
     * @return [type]      [description]
     */
    public function closeCidByUid()
    {
        $conn = RedisUtils::get($this->key['conn']);
        if (empty($conn)) {
            $conn = [];
        }

        foreach ($conn as $k => $v) {
            if ($v['uid'] == $this->uid) {
                unset($conn[$k]);
                RedisUtils::set($this->key['conn'], $conn);
                return true;
            }
        }
        return false;
    }

    /**
     * 获取牌桌基本信息
     * @return [type] [description]
     */
    public function getBaseTableInfo()
    {
        $hgame = new hGame($this->tid, $this->uid);
        $result['innings'] = $this->getTableCurInnings();
        $result['gameing'] = $this->getGameStatus();
        $result['myuid'] = $this->uid;
        $result['pos'] = $this->getTablePos();
        $result['config'] = $this->config;
        $result['user'] = $this->getTableAllUserBaseInfo($result['pos']);
        $result['tid'] = $this->tid;
        $result['settlement'] = $hgame->getSettlementStatus();
        return $result;
    }

    /**
     * 玩家加入牌桌
     * @return [type] [description]
     */
    public function joinTable()
    {
        // 判断玩家是否存在于其它牌桌
        $isTid = $this->playerHasATable();
        $tModel = new TableModel;

        if ($isTid !== 0) {
            if (empty($tModel->isExistTable($isTid))) {
                $this->destroyTableByTid($isTid);
            } else {
                return [
                    'code' => 201,
                    'msg'  => '您已存在其它牌桌，正在为您重连...',
                    'tid'  => $isTid
                ];
            }
        }

        // 判断牌桌是否存在
        if (empty($tModel->isExistTable($this->tid))) {
            $this->result['msg'] = '牌桌不存在';
            $this->destroyTable();
            return $this->result;
        }

        // 判断牌桌是否在游戏中
        if ($this->getGameStatus()) {
            $this->result['msg'] = '游戏中不可加入';
            return $this->result;
        }

        // 判断牌桌局数是否已满
        if ($this->getTableCurInnings() >= $this->config['innings']) {
            $this->result['msg'] = '牌桌已解散';
            return $this->result;
        }

        // 判断余额是否充足
        $uinfo = (new UserModel)->getBaseInfoByUid($this->uid);
        if ($uinfo['balance'] < $this->config['min_balance']) {
            $this->result['msg'] = '您的余额不符合牌桌的最低余额要求';
            return $this->result;
        }

        // 判断牌桌是否已满员
        if ($this->getTableNumber() >= $this->config['number']) {
            $this->result['msg'] = '牌桌已满人，无法加入';
            return $this->result;
        }

        // 加入
        RedisUtils::set($this->key['table'], $this->tid);
        return [
            'code' => 200,
            'msg'  => '加入牌桌成功,正在寻找位置...'
        ];
    }

    /**
     * 玩家加入牌桌位置
     * @return [type] [description]
     */
    public function joinTablePos()
    {
        if (!empty($this->uid)) {
            // 判断玩家是否重复添加
            if (!$this->getPlayerPos($this->uid)) {
                $pos = RedisUtils::get($this->key['pos']);
                if (empty($pos)) {
                    $pos = [];
                }
                for ($i = 0; $i < 5; $i++) {
                    if (empty($pos[$i])) {
                        $pos[$i] = $this->uid;
                        break;
                    }
                }
                RedisUtils::set($this->key['pos'], $pos);
            }
            return true;
        }
        return false;
    }

    /**
     * 玩家离开牌桌
     * @return [type] [description]
     */
    public function leaveTable()
    {
        if (empty($this->uid)) {
            return false;
        } else {
            if ($this->getGameStatus()) {
                return false;
            }

            $pos = RedisUtils::get($this->key['pos']);
            if (empty($pos)) {
                $pos = [];
            }

            RedisUtils::rm($this->key['table']);
            RedisUtils::rm($this->key['userinfo'].$this->uid);
            foreach ($pos as $k => $v) {
                if ($v == $this->uid) {
                    unset($pos[$k]);
                    break;
                }
            }
            $this->closeCidByUid();
            RedisUtils::set($this->key['pos'], $pos);
            return true;
        }
    }

    /**
     * 解散房间
     * @return [type] [description]
     */
    public function destroyTable()
    {
        (new TableModel)->deleteTable($this->tid);
        foreach ($this->key as $k => $v) {
            RedisUtils::rm($v);
        }

        return true;
    }

    /**
     * 解散房间
     * @return [type] [description]
     */
    public function destroyTableByTid($tid)
    {
        (new TableModel)->deleteTable($tid);
        foreach ($this->key as $k => $v) {
            RedisUtils::rm($v);
        }

        return true;
    }

    /**
     * 判断是否解散房间
     * @return boolean [description]
     */
    public function isDestyorTable()
    {
        $match = $this->config['innings'];
        $cur = $this->getTableCurInnings();
        if ($cur >= $match) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取牌桌人数
     * @return [type] [description]
     */
    public function getTableNumber()
    {
        $pos = RedisUtils::get($this->key['pos']);
        if (empty($pos)) {
            return 0;
        }
        return count($pos);
    }

    /**
     * 获取玩家位置
     * @param  [type] $uid [description]
     * @return [type]      [description]
     */
    public function getPlayerPos($uid)
    {
        $pos = RedisUtils::get($this->key['pos']);
        if (empty($pos)) {
            return false;
        }

        foreach ($pos as $k => $v) {
            if ($v == $uid) {
                return $k;
            }
        }
        return false;
    }

    /**
     * 根据位置获取玩家uid
     * @param  [type] $pos [description]
     * @return [type]      [description]
     */
    public function getUidByPos($pos)
    {
        $list = RedisUtils::get($this->key['pos']);
        if (empty($list)) {
            return false;
        }

        foreach ($list as $k => $v) {
            if ($k == $pos) {
                return $v;
            }
        }
        return false;
    }

    /**
     * 根据自己的uid获取上一家的位置
     * @param  [type] $uid [description]
     * @return [type]      [description]
     */
    public function getBeforePos()
    {
        $pos = RedisUtils::get($this->key['pos']);
        if (empty($pos)) {
            return false;
        }

        $curPos = $this->getPlayerPos($this->uid);
        if ($curPos == 0) {
            $beforePos = count($pos) - 1;
        } else {
            $beforePos = $curPos - 1;
        }
        return $beforePos;
    }

    /**
     * 根据自己的uid获取下一家的位置
     * @param  [type] $uid [description]
     * @return [type]      [description]
     */
    public function getNextPos()
    {
        $pos = RedisUtils::get($this->key['pos']);
        if (empty($pos)) {
            return false;
        }

        $curPos = $this->getPlayerPos($this->uid);
        if ($curPos == count($pos) - 1) {
            $nextPos = 0;
        } else {
            $nextPos = $curPos + 1;
        }
        return $nextPos;
    }

    /**
     * 玩家存在于一个牌桌
     * @return [type] [description]
     */
    public function playerHasATable()
    {
        $table = RedisUtils::get($this->key['table']);
        if (empty($table)) {
            return 0;
        }
        return (int)$table;
    }

    /**
     * 获取牌桌上所有玩家
     * @return [type] [description]
     */
    public function getTablePos()
    {
        $pos = RedisUtils::get($this->key['pos']);
        if (empty($pos)) {
            return [];
        }
        return $pos;
    }

    /**
     * 获取牌桌上所有玩家基本信息
     * @return [type] [description]
     */
    public function getTableAllUserBaseInfo($pos)
    {
        if (empty($pos)) {
            return [];
        }

        $newUserList = [];
        foreach ($pos as $k => $v) {
            $newUserList[$k] = $this->getUserinfo($v);
        }
        return $newUserList;
    }

    /**
     * 牌桌配置
     * @return [type] [description]
     */
    public function tableConfig()
    {
        $config = RedisUtils::get($this->key['config']);
        if (empty($config)) {
            $tModel = new TableModel;
            $config = $tModel->get($this->tid);
        }
        RedisUtils::set($this->key['config'], $config);
        $this->config = $config;
    }

    /**
     * 获取牌桌当前局数
     * @return [type] [description]
     */
    public function getTableCurInnings()
    {
        $innings = RedisUtils::get($this->key['innings']);
        $innings = empty($innings) ? 0 : $innings;

        return $innings;
    }

    /**
     * 获取游戏状态
     * @return [type] [description]
     */
    public function getGameStatus()
    {
        $status = RedisUtils::get($this->key['status']);
        $status = empty($status) ? false : $status;

        return $status;
    }

    /**
     * 获取用户的信息
     * @param  [type] $uid [description]
     * @return [type]      [description]
     */
    public function getUserinfo($uid)
    {
        $uinfo = RedisUtils::get($this->key['userinfo'].$uid);
        if (empty($uinfo)) {
            $tmp = (new UserModel)->getBaseInfoByUid($uid);
            $uinfo = [
                'name'  => $tmp['username'],
                'uid'   => $tmp['uid'],
                'type'  => $tmp['type'], // 0-普通 1-透视 2-好牌 3-全部
                'balance' => $tmp['balance'],
                'bet'     => 0,
                'status'  => $this->isMaster($uid) ? 2 : 0, // 0-未准备 1-已准备 2-房主
            ];
        }
        RedisUtils::set($this->key['userinfo'].$uid, $uinfo);
        return $uinfo;
    }

    /**
     * 设置用户信息
     *
     * @param [type] $uid [description]
     * @param [type] $bet 跟注金额
     */
    public function setUserinfo($uid, $bet)
    {
        $muinfo = (new UserModel)->getBaseInfoByUid($uid);
        $ruinfo = RedisUtils::get($this->key['userinfo'].$uid);
        $newInfo = [
            'name' => $muinfo['username'],
            'uid'  => $muinfo['uid'],
            'type' => $muinfo['type'],
            'balance' => $muinfo['balance'],
            'bet'  => $ruinfo['bet'] + $bet,
            'status' => $ruinfo['status']
        ];

        RedisUtils::set($this->key['userinfo'].$uid, $newInfo);
    }

    /**
     * 房主
     * @param  [type]  $uid [description]
     * @return boolean      [description]
     */
    public function isMaster($uid)
    {
        $tModel = new TableModel;
        $map = [
            'uid' => $uid,
            'id'  => $this->tid
        ];
        if ($tModel->where($map)->count() > 0) {
            return true;
        }
        return false;
    }

    /**
     * 获取投注总额
     *
     * @return [type] [description]
     */
    public function getTotalBet()
    {
        $pos = $this->getTablePos();
        $userlist = $this->getTableAllUserBaseInfo($pos);

        $total = 0;
        foreach ($userlist as $k => $v) {
            $total += $v['bet'];
        }
        return $total;
    }

    /**
     * 获取总人数
     *
     * @return [type] [description]
     */
    public function getTotalNumber()
    {
        $pos = $this->getTablePos();
        return count($pos);
    }

    /**
     * 获取当前牌局战绩
     *
     * @return [type] [description]
     */
    public function getCurMatchResults()
    {
        $match = $this->getTableCurInnings();
        $results = (new UserGradeModel)->getCurMatch($this->tid, $match);
        return $results;
    }
}
